from django.utils.deprecation import MiddlewareMixin
import redis,json,re
from rest_framework_jwt.utils import jwt_decode_handler
from jwt.exceptions import DecodeError, ExpiredSignatureError
from django.http import JsonResponse


#
class MyRBAC(MiddlewareMixin):

    def __init__(self, handler):
        super(MyRBAC, self).__init__(handler)

        # 初始化redis连接
        self.redis_cli = redis.Redis(host="localhost", port=6379, password='123', db=3)

    # 预处理请求
    def process_request(self, request):

        # 1.获取请求的方法，路径
        method = request.method.lower()
        path_info = request.path_info[1:]

        # 2.判断当前的请求是否为登录、admin
        # 这些请求需要放过去，进入路由匹配
        if re.findall(r"login|^admin|sms_code", path_info, re.I):
            # 放过去
            return None

        # 3. 其他的常规请求
        # 验证是否登录: 鉴权
        payload = self.validate_token(request)

        if payload:
            # 用户已登录
            # 4.判断当前用户对当前url是否又访问的权限
            print("解析的payload的数据:", payload)
            # 根据用户的id获取所有的权限
            key = "user_permissions_%s"%(payload.get("user_id"))
            # 获取权限列表
            permissions_list = json.loads(self.redis_cli.get(key).decode())

            # 检查权限能否与请求的url匹配
            for permission in permissions_list:
                if permission.startswith(method):
                    # 进一步匹配正则部分的路由
                    re_path = permission.split()[1]
                    if re.findall(re_path, path_info, re.I):
                        return None

            # 不具有权限
            return JsonResponse({"code": 403, "msg": "没有权限"})

        else:
            # 未登录
            return JsonResponse({"code": 403, "msg": "未登录"})


    @staticmethod
    def validate_token(request):
        # 获取token
        token = request.headers.get("Authorization")

        if not token:
            return False

        token = token.split()[1]

        # 解码token
        try:
            payload = jwt_decode_handler(token)

        except DecodeError:
            return False

        except ExpiredSignatureError:
            return False

        return payload

    def process_view(self, callback, *args, **kwargs):
        ...

    def process_exception(self, request, exception):

        ...
